/*******************************************************************************
 * Copyright (c) 2003 Boris Pruessmann and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Common Public License v0.5 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.ui.internal;

import net.sourceforge.perforce.api.CharSetEnum;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:boris@pruessmann.org">Boris Pruessmann</a>
 */
public class ServerDetailComposite extends Composite {
  //----------------------------------------------------------------------------
  // Public Constants

  /** Constant: Show Connection Group. */
  public static final int CONNECTION = 0x0001;
  /** Constant: Show Authentication Group. */
  public static final int AUTHENTICATION = 0x0002;

  // ---------------------------------------------------------------------------
  // Private Constants

  /** Constant: Perforce's default port. */
  private static final int DEFAULT_PORT = 1666;
  /** Constant: Text that will be shown in character set combo box. */
  private static final String[] characterSetDescriptions =
      {"no conversion", "eucjp", "iso8859-1", "shiftjis", "utf8", "winansi",};
  /**
   * Constant: Array fo CharSetEnums that correspond to entries in character set
   * combo.
   */
  private static final CharSetEnum[] characterSets =
      {CharSetEnum.NOCONV, CharSetEnum.EUCJP, CharSetEnum.ISO8859_1, CharSetEnum.SHIFTJIS,
          CharSetEnum.UTF_8, CharSetEnum.WIN_US_ANSI,};

  // ---------------------------------------------------------------------------
  // Private Variables

  /** Indicates which group controls are visible. */
  private int visibleGroups;
  /** Stores the server address. */
  private Text serverText;
  /** Stores the "Default Port" button. */
  private Button defaultPortButton;
  /** Stores the "Custom Port" button. */
  private Button customPortButton;
  /** Stores the custom port. */
  private Text customPortText;
  /** Stores the client name. */
  private Text clientText;
  /** Stores the host name. */
  private Text hostText;
  /** Stores the user name. */
  private Text userText;
  /** Stores the password. */
  private Text passwordText;
  /** Stores the character set. */
  private Combo characterSetCombo;
  /** Stores the "Perform Background Updates" button. */
  private Button backgroundUpdateButton;
  /** Stores the "Validate on Finish" Button. */
  private Button validateButton;

  // -------------------------------------------------------------------------
  // Public Constructors

  /**
   * Constructor for ServerDetailComposite.
   * 
   * @param parent the parent composite.
   */
  public ServerDetailComposite(Composite parent) {
    this(parent, CONNECTION | AUTHENTICATION);
  }

  /**
   * Constructor for ServerDetailComposite.
   * 
   * @param parent the parent composite.
   * @param theVisibleGroups indicator for the visible controls.
   */
  public ServerDetailComposite(Composite parent, int theVisibleGroups) {
    super(parent, SWT.NONE);
    visibleGroups = theVisibleGroups;

    createChildControls(this);

    if ((visibleGroups & CONNECTION) > 0) {
      SelectionListener radioSelectionListener = new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
          customPortText.setEnabled(customPortButton.getSelection());
        }
      };
      defaultPortButton.addSelectionListener(radioSelectionListener);
      customPortButton.addSelectionListener(radioSelectionListener);
    }
  }

  //----------------------------------------------------------------------------
  // -- Public Methods

  /**
   * Called to set the composite's detail information aka. content.
   * 
   * @param serverDetail the server details.
   */
  public void setServerDetail(ServerDetail serverDetail) {
    if ((visibleGroups & CONNECTION) > 0) {
      serverText.setText(serverDetail.getServerAddress());

      int serverPort = serverDetail.getServerPort();
      if (serverPort == DEFAULT_PORT) {
        defaultPortButton.setSelection(true);
        customPortText.setText(""); //$NON-NLS-1$
        customPortText.setEnabled(false);
      } else {
        customPortButton.setSelection(true);
        customPortText.setText("" + serverDetail.getServerPort());
        customPortText.setEnabled(true);
      }
    }

    if ((visibleGroups & AUTHENTICATION) > 0) {
      clientText.setText(serverDetail.getClient());
      hostText.setText(serverDetail.getHost());
      userText.setText(serverDetail.getUser());
      passwordText.setText(serverDetail.getPassword());
    }

    final CharSetEnum charSet = serverDetail.getCharacterSet();
    for (int i = 0; i < characterSets.length; i++) {
      if (characterSets[i] == charSet) {
        characterSetCombo.select(i);
      }
    }

    backgroundUpdateButton.setSelection(serverDetail.getBackgroundUpdates());
  }

  /**
   * Call this method to retrieve the composite's server detail.
   * 
   * @return the server detail.
   */
  public ServerDetail getServerDetail() {
    String server = null;
    int port = -1;
    if ((visibleGroups & CONNECTION) > 0) {
      server = serverText.getText();

      if (customPortButton.getSelection()) {
        port = Integer.parseInt(customPortText.getText());
      } else {
        port = DEFAULT_PORT;
      }
    }

    final String client = clientText.getText();
    final String host = hostText.getText();
    final String user = userText.getText();
    final String password = passwordText.getText();
    final CharSetEnum characterSet = characterSets[characterSetCombo.getSelectionIndex()];
    final boolean bgUpdates = backgroundUpdateButton.getSelection();

    final ServerDetail result =
        new ServerDetail(server, port, client, host, user, password, characterSet, bgUpdates);
    return result;
  }

  /**
   * Call this method to retrieve the state of the validation flag.
   * 
   * @return the state of the validation toggle.
   */
  public boolean getValidation() {
    return validateButton.getSelection();
  }

  /** Called to set the composite's validation control's selection. */
  public void setValidation(boolean validate) {
    validateButton.setSelection(validate);
  }

  @Override
  public boolean setFocus() {
    if ((visibleGroups & CONNECTION) > 0) {
      return serverText.setFocus();
    } else if ((visibleGroups & AUTHENTICATION) > 0) {
      return clientText.setFocus();
    }

    return false;
  }

  //----------------------------------------------------------------------------
  // - Private Methods

  /** Called to create the composite's child controls. */
  protected Composite createChildControls(Composite composite) {
    composite.setLayout(new GridLayout());
    composite.setLayoutData(new GridData(GridData.FILL_BOTH));

    if ((visibleGroups & CONNECTION) > 0) {
      final Group connectionGroup = new Group(composite, SWT.NONE);
      final GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 2;

      connectionGroup.setLayout(gridLayout);
      connectionGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      connectionGroup.setText("Connection");
      {
        final Label label = new Label(connectionGroup, SWT.NONE);
        label.setText("&Server:");
      }
      {
        serverText = new Text(connectionGroup, SWT.BORDER);
        serverText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      }
      {
        defaultPortButton = new Button(connectionGroup, SWT.RADIO);
        final GridData gridData = new GridData();
        gridData.horizontalSpan = 2;
        defaultPortButton.setLayoutData(gridData);
        defaultPortButton.setText("Use &Default Port");
      }
      {
        customPortButton = new Button(connectionGroup, SWT.RADIO);
        final GridData gridData = new GridData();
        gridData.horizontalSpan = 1;
        customPortButton.setLayoutData(gridData);
        customPortButton.setText("Use Por&t:");
      }
      {
        customPortText = new Text(connectionGroup, SWT.BORDER);
        final GridData gridData = new GridData();
        gridData.widthHint = 80;
        customPortText.setLayoutData(gridData);
      }
    }
    if ((visibleGroups & AUTHENTICATION) > 0) {
      final Group authenticationGroup = new Group(composite, SWT.NONE);
      final GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 2;

      authenticationGroup.setLayout(gridLayout);
      authenticationGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      authenticationGroup.setText("Authentication");
      {
        final Label label = new Label(authenticationGroup, SWT.NONE);
        label.setText("&Client:");
      }
      {
        clientText = new Text(authenticationGroup, SWT.BORDER);
        clientText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      }
      {
        final Label label = new Label(authenticationGroup, SWT.NONE);
        label.setText("&Host:");
      }
      {
        hostText = new Text(authenticationGroup, SWT.BORDER);
        hostText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      }
      {
        final Label label = new Label(authenticationGroup, SWT.HORIZONTAL | SWT.SEPARATOR);
        final GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        gridData.horizontalSpan = 2;
        label.setLayoutData(gridData);
      }
      {
        final Label label = new Label(authenticationGroup, SWT.NONE);
        label.setText("&User:");
      }
      {
        userText = new Text(authenticationGroup, SWT.BORDER);
        userText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
      }
      {
        final Label label = new Label(authenticationGroup, SWT.NONE);
        label.setText("&Password:");
      }
      {
        passwordText = new Text(authenticationGroup, SWT.BORDER);
        passwordText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
        passwordText.setEchoChar('*');
      }
    }
    {
      final Group group = new Group(composite, SWT.NONE);
      final GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 2;
      group.setLayout(gridLayout);
      group.setText("I18N");
      group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      {
        final Label label = new Label(group, SWT.NONE);
        label.setText("Character &Set:");
      }
      {
        characterSetCombo = new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY);
        characterSetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        fillCharacterSetCombo();
      }
    }
    {
      backgroundUpdateButton = new Button(composite, SWT.CHECK);
      backgroundUpdateButton.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL));
      backgroundUpdateButton.setText("P&erform Background Updates");
    }
    if ((visibleGroups & CONNECTION) > 0) {
      validateButton = new Button(composite, SWT.CHECK);
      validateButton.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL));
      validateButton.setText("&Validate Connection on Finish");
    }

    applyDialogFont(composite);

    return composite;
  }

  /** Called to fill the Character Set Combo with values. */
  private void fillCharacterSetCombo() {
    for (int i = 0; i < characterSetDescriptions.length; i++) {
      characterSetCombo.add(characterSetDescriptions[i]);
    }
  }

  /**
   * Called to apply the default dialog font to the given composite and its
   * children.
   * 
   * @param composite the composite to which the font will be applied.
   */
  private void applyDialogFont(Composite composite) {
    // Just calling Dialog.applyDialogFont doesn't current work properly on
    // MacOS X 10.3
    final Control[] children = composite.getChildren();
    for (int i = 0; i < children.length; i++) {
      if (!(children[i] instanceof Composite)) {
        Dialog.applyDialogFont(children[i]);
      } else {
        applyDialogFont((Composite) children[i]);
      }
    }
  }
}
